#include "common.h"

Image createImage(int h, int w){
	int i;
	Image img;
	img.h = h;
	img.w = w;
	img.pixels = (unsigned char**) calloc(h, sizeof(unsigned char*));

	for(i = 0; i < h; i++)
		img.pixels[i] = (unsigned char*) calloc(w, sizeof(unsigned char));
	return img;
}

IntegralImage createIntegralImage(int h, int w)
{
    int i;
	IntegralImage img;
	img.h = h;
	img.w = w;
	img.pixels = (unsigned int**) calloc(h, sizeof(unsigned int*));

	for(i = 0; i < h; i++)
		img.pixels[i] = (unsigned int*) calloc(w, sizeof(unsigned int));
	return img;
}

void copyImage(Image dst, Image src) {
	int i, j, h, w;
	h = src.h;
	w = src.w;

    for(i = 0; i < h; i++){
		for(j = 0; j < w; j++){
			dst.pixels[i][j] = src.pixels[i][j];
		}
	}
}

int inImage(int y, int x, int h, int w)
{
        return (y >= 0 && y < h && x >=0 && x < w);
}

void deleteImage(Image input) {
        int i;
        for(i = 0; i < input.h; i ++){
                free(input.pixels[i]);
        }
        free(input.pixels);
}

void printImage(Image input, char* fileName){
	int i, j;
	/// open file
	FILE * f = fopen(fileName, "w");

	/// write to file
	for (i = 0; i < input.h; i ++) {
		for (j = 0; j < input.w; j++)

			if(input.pixels[i][j]) fprintf(f, "%d", input.pixels[i][j]);
			else fprintf(f, ".");
		fprintf(f, "\n");
	}
	fflush(f);
	fclose(f);
}

void printFeatureImage(Image input, char* fileName) {
	unsigned char pixVal;
	int i, j;
	/// open file
	FILE * f = fopen(fileName, "w");

	/// write to file
	for (i = 0; i < input.h; i ++) {
		for (j = 0; j < input.w; j++) {
			pixVal = input.pixels[i][j];

			if(pixVal == '.') fprintf(f, ".");
			else fprintf(f, "%d", pixVal);
		}
		fprintf(f, "\n");
	}
	fclose(f);
}


int getNeighbor(Image input, int dir, int x, int y)
{
	switch (dir) {
	case RIGHT:     x += 1;         break;
	case RIGHT_TOP:	x += 1;	y -= 1;	break;
	case TOP:       y -= 1;         break;
	case LEFT_TOP:	x -= 1;	y -= 1;	break;
	case LEFT:		x -= 1;     	break;
	case LEFT_BOT:	x -= 1;	y += 1;	break;
	case BOT:		y += 1; 		break;
	case RIGHT_BOT: x += 1; y += 1;	break;
	}
	if (inImage(y, x, input.h, input.w)) {
		return input.pixels[y][x];
	}
	return -1;
}

int getNeighborForMatch(Image input, int dir, int x, int y){
	return getNeighbor(input, dir, x, y) > 0 ? 1:0;
}

void setNeighbor(Image input, int dir, int x, int y, int val)
{
	switch (dir) {
	case RIGHT:     x += 1;         break;
	case RIGHT_TOP:	x += 1;	y -= 1;	break;
	case TOP:       y -= 1;         break;
	case LEFT_TOP:	x -= 1;	y -= 1;	break;
	case LEFT:		x -= 1;     	break;
	case LEFT_BOT:	x -= 1;	y += 1;	break;
	case BOT:		y += 1; 		break;
	case RIGHT_BOT: x += 1; y += 1;	break;
	}
	if (inImage(y, x, input.h, input.w)) {
		input.pixels[y][x] = val;
	}
}

void setRect(Rect *rect, int x, int y, int w, int h) {
    rect->x = x;
    rect->y = y;
    rect->w = w;
    rect->h = h;
}

void addPointToRect(Rect *rect, int x, int y) {
    int right = rect->x + rect->w - 1;
    int bottom = rect->y + rect->h - 1;

    rect->x = rect->x > x ? x: rect->x;
    rect->y = rect->y > y ? y: rect->y;

    rect->w = right < x ? x - rect->x + 1: right - rect->x + 1;
    rect->h = bottom < y ? y - rect->y + 1: bottom - rect->y + 1;
}
